package com.tycmc.common.dynamicloader;

import com.tycmc.common.util.Property;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@SuppressWarnings("rawtypes")
public class DynamicClassLoadUtil {

    private static DynamicClassLoadUtil single;

    private Map<String, DynamicClassLoader> loaders;

    private Map<String, Map<String, Class>> caches;

    private String libPath;

    private Lock lock = new ReentrantLock();

    private boolean isUpdateStarted = false;

    private int interval;

    private DynamicClassLoadUtil() {
        libPath = Property.getProperty("libPath");
        loaders = new HashMap<>();
        caches = new HashMap<>();
    }

    private void loadJar(String jarName) throws MalformedURLException {
        DynamicClassLoader loader = new DynamicClassLoader(new URL[]{new URL(libPath + jarName)},
                Thread.currentThread().getContextClassLoader());
        loaders.put(jarName, loader);
    }

    public void reInit() {
        lock.lock();
//		Map<String, TreatClassLoader> tmp = new HashMap<String, TreatClassLoader>();
        for (String key : loaders.keySet()) {
            try {
                loaders.get(key).close();
                loadJar(key);
            } catch (IOException e) {
                // TODO Auto-generated catch block
//				LogRecord.error(key + "包重加载出现问题", e);
            }
        }
        caches.clear();
        System.out.println("init");
        lock.unlock();
    }

    public static Class getTest() {
        return null;
    }

    public Object loadClass(String jarName, String className)
            throws ClassNotFoundException, MalformedURLException, InstantiationException, IllegalAccessException {
        lock.lock();
        try {
            if (loaders.containsKey(jarName)) {
                if (caches.containsKey(jarName)) {
                    if (caches.get(jarName).containsKey(className)) {
                        return caches.get(jarName).get(className).newInstance();
                    } else {
                        Class c = loaders.get(jarName).loadClass(className);
                        caches.get(jarName).put(className, c);
                        return c.newInstance();
                    }
                } else {
                    System.out.println("load jar: " + jarName + "\nClass: " + className);
                    Map<String, Class> cache = new HashMap<>();
                    Class c = loaders.get(jarName).loadClass(className);
                    cache.put(className, c);
                    caches.put(jarName, cache);
                    return c.newInstance();
                }
            } else {
                System.out.println("load jar: " + jarName + "\nClass: " + className);
                loadJar(jarName);
                Map<String, Class> cache = new HashMap<>();
                Class c = loaders.get(jarName).loadClass(className);
                cache.put(className, c);
                caches.put(jarName, cache);
                return c.newInstance();
            }
        } catch (ClassNotFoundException | MalformedURLException e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    public synchronized static DynamicClassLoadUtil getLoader() {
        if (single == null) {
            single = new DynamicClassLoadUtil();
            //single.startUpdate();
        }
        return single;
    }

    public void startUpdate() {
        if (!isUpdateStarted) {
            new Thread(() -> {
                // TODO Auto-generated method stub
                while (true) {
                    try {
                        Thread.sleep(interval);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    //reInit();
                }
            }).start();
        }
    }

}
